﻿//
// Copyright (c) 2024 BPer
//

#include <bperice/BPerRtcStun.h>
#include <bperice/BPerRtcSocket.h>
#include <bperzlm/BPerZlmConnection.h>
#include <bperrtc/BPerRtcConnection.h>

#include <bpersdp/BPerSdp.h>
#include <bperjson/BPerJson.h>
#include <bperutil/sys/BPerLog.h>
#include <bperutil/sys/BPerCString.h>
#include <bperutil/sys/BPerHttp.h>
#define BPer_SDP_BUFFERLEN 1024*12

typedef struct{
	int32_t retcode;
	char* sdp;
	char* id;
}ZlmSdpResponseType;

void bPer_destroy_zlmresponse(ZlmSdpResponseType* zlm){
	if(zlm==NULL) return;
	bPer_free(zlm->sdp);
	bPer_free(zlm->id);
}

int32_t bPer_zlm_query(BPerRtcSession* session,ZlmSdpResponseType* zlm,int32_t isplay,char* ip,int32_t port,char* purl, char* psdp)
{

	int32_t err=BPer_Ok;

	char* sdp=(char*)bPer_calloc(1,BPer_SDP_BUFFERLEN);
	if(bPer_http_post(BPerFalse,session->context.avinfo->sys.familyType,sdp,ip, port, purl, (uint8_t*)psdp, bPer_strlen(psdp))){
		bPer_free(sdp);
		return bPer_error_wrap(1,"query zlm sdp failure!");
	}

	BPerJsonReader reader;
	char* p=bPer_strstr(sdp,"{");
	if(p==NULL) return ERROR_STRING;

	if(bPer_create_jsonReader(&reader,p)!=BPer_Ok){
		bPer_error("read zlm response json error!");
		err=ERROR_STRING;
		goto cleanup;
	}

	BPerJson* jcode = reader.getObjectItemCaseSensitive(reader.session, "code");
	if (reader.isNumber(jcode))
	{
		err=jcode->valueint==0?BPer_Ok:ERROR_SERVER_ConnectFailure;
		if(err!=BPer_Ok) goto cleanup;
	}

	zlm->retcode=jcode->valueint;

	BPerJson* sessionid = reader.getObjectItemCaseSensitive(reader.session, "id");
	BPerJson* jsdp = reader.getObjectItemCaseSensitive(reader.session, "sdp");


	if (reader.isString(sessionid) && (sessionid->valuestring != NULL))
	{
		zlm->id=(char*)bPer_calloc(bPer_strlen(sessionid->valuestring)+1,1);
		bPer_memcpy(zlm->id,sessionid->valuestring,bPer_strlen(sessionid->valuestring));

	}

	if (reader.isString(jsdp) && (jsdp->valuestring != NULL))
	{
		zlm->sdp=(char*)bPer_calloc(bPer_strlen(jsdp->valuestring)+1,1);
		bPer_cstr_replace(jsdp->valuestring,zlm->sdp, "\r\n", "\n");
	}

	cleanup:
	bPer_destroy_jsonReader(&reader);
	bPer_free(sdp);
	return err;

}


int32_t bPer_zlm_doHandleSignal(BPerRtcSession* session,ZlmSdpResponseType* zlm,char* sdp,int32_t localport, BPerRtcDirection role) {
	int32_t err = BPer_Ok;

	char apiurl[256] ;
	bPer_memset(apiurl,0,sizeof(apiurl));

	bPer_sprintf(apiurl,sizeof(apiurl),"index/api/webrtc?app=%s&stream=%s&type=%s", session->context.streamConfig->app,session->context.streamConfig->stream,role==BPerRecvonly?"play":"push");
	err=bPer_zlm_query(session,zlm,role==BPerRecvonly?1:0,(char*)session->context.streamConfig->remoteIp,session->context.streamConfig->remotePort,apiurl, sdp);

	return err;
}

int32_t bPer_zlm_connectRtcServer(BPerRtcConnection* conn){
	int err=BPer_Ok;
	ZlmSdpResponseType zlm;
	BPerRtcSession* session=conn->session;
	bPer_memset(&zlm,0,sizeof(ZlmSdpResponseType));
	char *tsdp=NULL;
	conn->createOffer(session, &tsdp);
	if(tsdp) conn->setLocalDescription(session,tsdp);
    if ((err=bPer_zlm_doHandleSignal(session,&zlm,tsdp,session->context.streamConfig->localPort,session->context.streamConfig->direction))  == BPer_Ok) {
		conn->setRemoteDescription(conn->session,zlm.sdp);
	}
	bPer_free(tsdp);
	bPer_destroy_zlmresponse(&zlm);
    return err;
}
